/*
 * graph2D
 * Copyright (c) 2011 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#import <StoreKit/StoreKit.h>

@interface Kiosk_impl : NSObject<SKProductsRequestDelegate, SKPaymentTransactionObserver>
{
	bool requesting;
	bool success;
}
- (id)init;
- (void)dealloc;
- (bool)valid;
- (bool)request:(NSString*)productIdentifier;
- (bool)busy;
- (bool)result;
@end

@implementation Kiosk_impl

- (id)init
{
	if((self = [super init]) != nil)
	{
		requesting = false;
		success = false;
	}

	return self;
}

////////////////////////////////////////////////////////////////////////////////
- (void)dealloc
{
	while(requesting)
	{
		[NSThread sleepForTimeInterval:0.5];
	}

	[super dealloc];
}

////////////////////////////////////////////////////////////////////////////////
- (bool)valid
{
	return [SKPaymentQueue canMakePayments];
}

////////////////////////////////////////////////////////////////////////////////
- (bool)request:(NSString*)productIdentifier
{
	if(requesting)
		return false;

	[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

	NSSet* productIdentifiers = [NSSet setWithObject:productIdentifier];
	SKProductsRequest* skProductRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
	skProductRequest.delegate = self;
	[skProductRequest start];

	requesting = true;
	success = false;

	return true;
}

////////////////////////////////////////////////////////////////////////////////
- (bool)busy
{
	return requesting;
}

////////////////////////////////////////////////////////////////////////////////
- (bool)result
{
	while(requesting)
	{
		[NSThread sleepForTimeInterval:0.5];
	}

	return success;
}

////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark SKProductsRequestDelegate

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
	if(response == nil)
	{
		NSLog(@"Product Response is nil");
		return;
	}

	// 確認できなかったidentifierをログに記録
	for(NSString* identifier in response.invalidProductIdentifiers)
	{
		NSLog(@"invalid product identifier: %@", identifier);
	}

	// 確認できたidentifierをログに記録
	for(SKProduct* product in response.products)
	{
		NSLog(@"valid product identifier: %@", product.productIdentifier);

		SKPayment* payment = [SKPayment paymentWithProduct:product];
		[[SKPaymentQueue defaultQueue] addPayment:payment];
	}
}

////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark SKPaymentTransactionObserver

- (void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*)transactions
{
	BOOL purchasing = YES;

	for(SKPaymentTransaction* transaction in transactions)
	{
		switch(transaction.transactionState)
		{
		// 購入中
		case SKPaymentTransactionStatePurchasing:
			{
				NSLog(@"Payment Transaction Purchasing");
				break;
			}
		// 購入成功
		case SKPaymentTransactionStatePurchased:
			{
				NSLog(@"Payment Transaction END Purchased: %@", transaction.transactionIdentifier);
				purchasing = NO;
				success = true;
				[queue finishTransaction:transaction];
				break;
			}
		// 購入失敗
		case SKPaymentTransactionStateFailed:
			{
				NSLog(@"Payment Transaction END Failed: %@ %@", transaction.transactionIdentifier, transaction.error);
				if(transaction.error.code != SKErrorPaymentCancelled)
				{
					// 必要に応じてここでエラーを表示する
				}
				purchasing = NO;
				[queue finishTransaction:transaction];
				break;
			}
		// 購入履歴復元
		case SKPaymentTransactionStateRestored:
			{
				NSLog(@"Payment Transaction END Restored: %@", transaction.transactionIdentifier);
				purchasing = NO;
				[queue finishTransaction:transaction];
				break;
			}
		}
	}

	if(purchasing == NO)
	{
		requesting = false;
	}
}

@end

////////////////////////////////////////////////////////////////////////////////
namespace Graph2D
{
	namespace Implementation
	{
		namespace Kiosk
		{
			void* initialize()
			{
				Kiosk_impl* self = [[Kiosk_impl alloc] init];

				return reinterpret_cast<void*>(self);
			}

			void finalize(void* instance)
			{
				Kiosk_impl* self = reinterpret_cast<Kiosk_impl*>(instance);

				[self release];
			}

			bool valid(void* instance)
			{
				Kiosk_impl* self = reinterpret_cast<Kiosk_impl*>(instance);

				return [self valid];
			}

			bool request(void* instance, const char* productIdentifier)
			{
				Kiosk_impl* self = reinterpret_cast<Kiosk_impl*>(instance);

				return [self request:[NSString stringWithUTF8String:productIdentifier]];
			}

			bool busy(void* instance)
			{
				Kiosk_impl* self = reinterpret_cast<Kiosk_impl*>(instance);

				return [self busy];
			}

			bool result(void* instance)
			{
				Kiosk_impl* self = reinterpret_cast<Kiosk_impl*>(instance);

				return [self result];
			}
		}
	}
}

